package com.mingyuean.demo.mybatis.binding;

import com.mingyuean.demo.mybatis.session.SqlSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

//映射器代理工厂：https://blog.csdn.net/qq_37855749/article/details/119544954

/**
 * @author MingYueAn
 * <p>  映射器代理工厂
 * <p>  2023/3/11 21:49
 * @version: 1.0
 */
public class MapperProxyFactory<T> {

    private static final Logger log = LoggerFactory.getLogger(MapperProxyFactory.class);

    /**
     * mapper接口的类对象
     */
    private final Class<T> mapperInterfaceClass;
    /**
     * 缓存Mapper接口中的方法和对应的MapperMethod对象
     */
    private final Map<Method, MapperMethod> methodCache = new ConcurrentHashMap<>();

    /**
     * 获取mapper接口的类对象
     *
     * @return mapper接口的类对象
     */
    public Class<T> getMapperInterface() {
        return mapperInterfaceClass;
    }

    /**
     * 获取方法缓存map
     *
     * @return Map<Method, MapperMethod>
     */
    public Map<Method, MapperMethod> getMethodCache() {
        return methodCache;
    }

    /**
     * 构造方法
     *
     * @param mapperInterfaceClass mapper接口的类对象
     */
    public MapperProxyFactory(Class<T> mapperInterfaceClass) {
        log.debug("获取到的mapper接口：{}", mapperInterfaceClass.getName());
        this.mapperInterfaceClass = mapperInterfaceClass;
    }

    /**
     * 创建Mapper接口的代理实例
     *
     * @param sqlSession SqlSession对象，负责执行SQL语句
     * @return Mapper接口的代理实例
     */
    public T newInstance(SqlSession sqlSession) {
        log.debug("{}---->{}", mapperInterfaceClass.getName(), sqlSession);
        // 处理器
        final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, methodCache, mapperInterfaceClass);
        // 使用代理，获取实例化对象
        final Object obj = Proxy.newProxyInstance(
                mapperInterfaceClass.getClassLoader(),
                new Class[]{mapperInterfaceClass},
                mapperProxy
        );
        return (T) obj;
    }
}
